package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.webservice.SoapClient;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.XML;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.constant.OrderConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.constant.IpAddressConstant;
import com.ruoyi.system.domain.ERP.*;
import com.ruoyi.system.domain.HUAWEI.*;
import com.ruoyi.system.domain.InterfaceLog;
import com.ruoyi.system.domain.Pull.MaterialPlug;
import com.ruoyi.system.domain.SetModel;
import com.ruoyi.system.domain.WMS.*;
import com.ruoyi.system.domain.base.*;
import com.ruoyi.system.domain.dock.OrderInfoDTO;
import com.ruoyi.system.domain.MES.OrderInfoUpDTO;
import com.ruoyi.system.domain.function.ProdOrder;
import com.ruoyi.system.domain.function.ProdOrderDTO;
import com.ruoyi.system.domain.function.ProdPlan;
import com.ruoyi.system.domain.mail.MailInfoDTO;
import com.ruoyi.system.domain.prod.ProdCountByTaskTonDTO;
import com.ruoyi.system.enums.TaskEnum;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.mapper.HUAWEI.*;
import com.ruoyi.system.mapper.pull.MaterialPlugMapper;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.mail.MailApplication;
import com.ruoyi.system.utils.InterfaceLogUtil.InterfaceLogUtil;
import com.ruoyi.system.utils.huaweiInterfaceUtil.HuaweiInterfaceHttps;
import lombok.extern.log4j.Log4j;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 生产计划Service业务层处理
 *
 * @author ruoyi
 * @date 2023-02-10
 */
@Service
public class ProdPlanServiceImpl extends ServiceImpl<ProdPlanMapper, ProdPlan> implements IProdPlanService {
    @Autowired
    private InterfaceLogMapper interfaceLogMapper;
    @Autowired
    private ProdOrderMapper prodOrderMapper;
    @Autowired
    private BaseBomInfoMapper baseBomInfoMapper;
    @Autowired
    private BaseMaterialMapper baseMaterialMapper;
    @Autowired
    private ProdPlanMapper prodPlanMapper;
    @Autowired
    private BomInfoErpMapper bomInfoErpMapper;
    @Autowired
    private IBaseSerialNumberService iBaseSerialNumberService;
    @Autowired
    private SetModelMapper setModelMapper;
    @Autowired
    private BaseShopMapper baseShopMapper;
    @Autowired
    private MesOperationsMapper mesOperationsMapper;
    @Autowired
    private WmsQtMaterialMapper wmsQtMaterialMapper;
    @Autowired
    private MaterialPlugMapper materialPlugMapper;
    @Autowired
    private WMSService wmsService;
    @Autowired
    private IProdOrderService iProdOrderService;
    @Autowired
    private EmsCustomerSnMapper customerSnMapper;
    @Autowired
    private MailApplication mailApplication;
    @Autowired
    private EmsBarcodeAttributeMapper barcodeAttributeMapper;
    @Autowired
    private EmsBarcodeMaterialMapper barcodeMaterialMapper;
    @Autowired
    private EmsBarcodeRelationMapper barcodeRelationMapper;
    @Autowired
    private SoftwareMapper softwareMapper;
    @Autowired
    private ITBtpMtlCurriculumViateTiService tbService;
    @Autowired
    private SubmitTaskNoInfoMapper submitTaskNoInfoMapper;
    @Autowired
    private IEmsBarcodeShipmentService shipmentService;
    @Autowired
    private BaseStationMaterialMapper baseStationMaterialMapper;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private MaterialDataErpMapper materialDataErpMapper;
    //    @Autowired
//    private MyMQTTClient myMQTTClient;
//    @Autowired
//    private MyProducer myProducer;

    @Autowired
    private ProPlanOrderProcessErpMapper proPlanOrderProcessErpMapper;
    @Autowired
    private InterfaceLogUtil interfaceLogUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult issued(ProdOrderDTO dto) {
        ProdOrder prodOrder = prodOrderMapper.selectById(dto.getOrderId());
        BeanUtil.copyProperties(prodOrder, dto);

        //sap新增逻辑 根据新编码去物料主数据里面找到旧编码替换
        MaterialDataErp materialDataErp = materialDataErpMapper.selectOne(new QueryWrapper<MaterialDataErp>()
                .eq("inv_code", dto.getMaterialCode())
        );
        prodOrder.setMaterialCode(materialDataErp.getInvCodeOld());

        if (ObjectUtil.isNull(dto)) {
            throw new CustomException("下发数据不能为空！");
        }

        //是否已齐套
        if (!OrderConstants.Pending.equals(dto.getOrderState())) {
            return AjaxResult.error("下发失败：【还未齐套校验】");
        }

        //下发之前调用华为发料接口判断是否发料
//        Boolean boFi = this.findTaskDetail(dto.getTaskTon());
//        if (boFi == false) {
//            return AjaxResult.error("下发失败：【还未进行发料】");
//        }

        //调用wms接口发送订单信息
        Boolean aBoolean = this.requestProdWMS(dto);
        if (aBoolean == false) {
            return AjaxResult.error("下发失败：【wms下发订单接口异常】");
        }

        List<SubmitTaskNoInfo> subList = submitTaskNoInfoMapper.selectList(new QueryWrapper<SubmitTaskNoInfo>().eq("entity_name", dto.getTaskTon()));
        if (IterUtil.isEmpty(subList)) {
            //华为工单开工信息
            this.uploadKg(dto);
        }
        //发送订单任务到MES
        this.sendOrderMES(dto);

        ProdOrder po = prodOrderMapper.selectById(dto.getOrderId());
        if (po != null) {
            po.setOrderState(OrderConstants.Unexecuted);
            prodOrderMapper.updateById(po);
        }
        return AjaxResult.success("下发成功");
    }

    private Boolean findTaskDetail(String taskTon) {

        Boolean bo = false;
        FindTaskDetailDTO dto = new FindTaskDetailDTO();
        dto.setTaskNo(taskTon);
        String date = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        dto.setStartDate(date);
        Date previousWeek = DateUtil.offsetDay(new Date(), -7);
        String sevenDaysAgo = DateUtil.format(previousWeek, "yyyy-MM-dd HH:mm:ss");
        dto.setEndDate(sevenDaysAgo);
        dto.setAttribute1("");

        String body = HttpRequest.post(IpAddressConstant.HUAWEI_IP_FL)
                .header("X-HW-ID", "APP_Z01YQJ_LD")
                .header("X-HW-APPKEY", "nhug/78Mx2gKwEuhqJHdpg==")
                .header("Content-Type", "application/json")
                .body(JSONUtil.toJsonStr(dto))
                .execute().body();
        // 使用 Hutool 解析 JSON
        JSONObject jsonObject = JSONUtil.parseObj(body);
        // 获取body数组的第一个元素
        JSONArray bodyArray = jsonObject.getJSONArray("body");
        JSONObject bodyObject = bodyArray.getJSONObject(0);
        // 检查beginTime字段是否为空
        if (bodyObject.containsKey("beginTime") && !bodyObject.isNull("beginTime")) {
            String beginTime = bodyObject.getStr("beginTime");
            bo = true;
        }
        return bo;
    }


    private void uploadKg(ProdOrderDTO dto) {
        String startTime = DateUtil.format(DateUtil.offsetHour(new Date(), 1), "yyyy/MM/dd HH:mm:ss");
//        String xml ="<![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
//                "<SubmitTaskNoInfo>\n" +
//                "<Import>\n" +
//                "<EntityName>"+dto.getTaskTon()+"</EntityName>\n" +
//                "<WorkNumber>"+dto.getTaskTon()+"</WorkNumber>\n" +
//                "<StartTime>"+startTime+"</StartTime>\n" +
//                "<ShipmentTime></ShipmentTime>\n" +
//                "<Segment1></Segment1>\n" +
//                "<Segment2></Segment2>\n" +
//                "<Segment3></Segment3>\n" +
//                "<Segment4></Segment4>\n" +
//                "<Segment5></Segment5>\n" +
//                "</Import>\n" +
//                "</SubmitTaskNoInfo>]]>";

        String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?> <soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">   \n" +
                "<soap:Body>     <Get_Info_Frmbarcode xmlns=\"http://Auto.huawei.com.cn/\">       \n" +
                "<sTaskType>SubmitTaskNoInfoNew</sTaskType>       \n" +
                "<sImport><![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n" +
                "<SubmitTaskNoInfoNew>\n" +
                "  <Import>\n" +
                "      <EntityName>" + dto.getTaskTon() + "</EntityName>\n" +
                "      <WorkNumber>" + dto.getTaskTon() + "</WorkNumber>\n" +
                "      <StartTime>" + startTime + "</StartTime >\n" +
                "      <ShipmentTime></ShipmentTime>\n" +
                "      <Segment1></Segment1>\n" +
                "      <Segment2></Segment2>\n" +
                "      <Segment3></Segment3>\n" +
                "      <Segment4></Segment4>\n" +
                "      <Segment5></Segment5>\n" +
                "    </Import>\n" +
                "</SubmitTaskNoInfoNew>]]>\n" +
                "</sImport>     \n" +
                "</Get_Info_Frmbarcode>   \n" +
                "</soap:Body> \n" +
                "</soap:Envelope>";
        String date = DateUtil.format(new Date(), "yyyyMMdd'T'HHmmss'Z'");
        try {
            //改为https方式回传华为20250416
            String send = HuaweiInterfaceHttps.sendHuawei(HuaweiInterfaceHttps.serviceUriSoap, HuaweiInterfaceHttps.http_medhod_soap, xml, date);
//            SoapClient client = SoapClient.create("http://cmes.huawei.com/hw_manufacture/Midlayer.asmx")
//                    .setMethod("Get_Info_Frmbarcode", "http://Auto.huawei.com.cn/")
//                    .setParam("sTaskType", "SubmitTaskNoInfo")
//                    .setParam("sImport", xml);
//
//            // 发送请求，参数true表示返回一个格式化后的XML内容
//            // 返回内容为XML字符串，可以配合XmlUtil解析这个响应
//            String send = client.send(true);
            JSONObject object = XML.toJSONObject(send);
            Map map3 = JSONUtil.toBean(JSONUtil.toJsonStr(object), Map.class);
            Software software = new Software();
            software.setRes(JSONUtil.toJsonStr(map3));
            //回传华为工单开工时间日志记录
            SubmitTaskNoInfo submitTaskNoInfo = new SubmitTaskNoInfo();
            submitTaskNoInfo.setEntityName(dto.getTaskTon());
            submitTaskNoInfo.setWorkNumber(dto.getTaskTon());
            submitTaskNoInfo.setStartTime(startTime);
            submitTaskNoInfo.setRes(JSONUtil.toJsonStr(map3));
            submitTaskNoInfoMapper.insert(submitTaskNoInfo);
        } catch (Exception e) {
            //异常日志记录
            InterfaceLog interfaceLog = new InterfaceLog();
            interfaceLog.setSerialNumber(String.valueOf(new Date().getTime()));
            interfaceLog.setStartTime(new Date());
            interfaceLog.setInterfaceDirection("MOM->HUAWEI");
            interfaceLog.setPacketSize("");
            interfaceLog.setInterfaceRequest(dto.getTaskTon() + ";" + dto.getOrderCode() + ";" + DateUtil.format(new Date(), "yyyy/MM/dd HH:mm:ss"));
            interfaceLog.setEndTime(new Date());
            interfaceLog.setInterfaceResponse(e.getMessage());
            long be = DateUtil.between(interfaceLog.getStartTime(), interfaceLog.getEndTime(), DateUnit.MS);
            interfaceLog.setTimeConsuming(String.valueOf(be));
            interfaceLog.setCreateTime(new Date());
            interfaceLog.setInterfaceType("http");
            interfaceLog.setInterfaceName("华为工单开工时间");
            interfaceLogMapper.insert(interfaceLog);
        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult qtjy(ProdOrderDTO dto) {
        ProdOrder prodOrder = prodOrderMapper.selectById(dto.getOrderId());
        BeanUtil.copyProperties(prodOrder, dto);
        if (ObjectUtil.isNull(dto)) {
            throw new CustomException("齐套校验数据不能为空！");
        }
        ProdOrder po = prodOrderMapper.selectById(dto.getOrderId());
        //调用wms接口进行齐配套校验
        String res = this.requestOrderWMS(dto);
        if (po != null && "齐套校验成功".equals(res)) {
            po.setOrderState(OrderConstants.Pending);
            prodOrderMapper.updateById(po);
            // 获取当前类的代理对象
            ProdPlanServiceImpl proxy = applicationContext.getBean(ProdPlanServiceImpl.class);
            proxy.laliao(prodOrder, dto);
            return AjaxResult.success("齐套校验成功");
        }
        return AjaxResult.error(res);
    }

    /**
     * 拉料操作(子线程并行处理)
     */
    @Async("asyncExecutor")
    public void laliao(ProdOrder prodOrder, ProdOrderDTO dto) {
        String planCode = prodOrder.getPlanCode();
        ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("plan_code", planCode));
        String scddErpId = prodPlan.getScddErpId();
        List<BomInfoErp> listBom = bomInfoErpMapper.selectList(new QueryWrapper<BomInfoErp>().eq("scdd_erp_id", scddErpId));
        List<Long> plugIds = new ArrayList<>();
        listBom.stream().forEach(lb -> {
            MaterialPlug materialPlug = new MaterialPlug();
            MaterialPlug mat = materialPlugMapper.selectList(new QueryWrapper<MaterialPlug>().orderByDesc("plug_id")).get(0);
            materialPlug.setPlugNumbers(iBaseSerialNumberService.getSerialNumber("BL"));
            materialPlug.setMaterialCode(lb.getChildCode());
            materialPlug.setMaterialName(lb.getChildName());
            materialPlug.setLineName("hw电驱动电机1线");//这个要改一下
            materialPlug.setStationName("工位001");//这个要改一下
            materialPlug.setDeptName("生产部门");
            materialPlug.setDeptId(703L);//这个确定下补料下发的时候有没有把0带上
            materialPlug.setOrderCode(prodOrder.getOrderCode());
            materialPlug.setTaskTon(prodOrder.getTaskTon());
            materialPlug.setProductName(prodPlan.getProductName());
            materialPlug.setProductCode(prodPlan.getProductCode());
            materialPlug.setStatus(0);
            materialPlug.setUnit(lb.getUnit());
            materialPlug.setPlugNumber(lb.getBasicDosage() * dto.getOrderNumber());
            materialPlug.setLineCode("Line01");//这个要改一下
            materialPlug.setStationCode("OP10-1");//这个要改一下
            materialPlugMapper.insert(materialPlug);
            plugIds.add(materialPlug.getPlugId());
        });
        //进行物料下发
        wmsService.materialIssued(plugIds);
    }

    @Override
    public List<WmsQtMaterial> qtjyInfo(ProdOrderDTO dto) {
        QueryWrapper<WmsQtMaterial> qw = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(dto)) {
            if (StrUtil.isNotEmpty(dto.getOrderId())) {
                qw.eq("order_id", dto.getOrderId());
            }
            if (StrUtil.isNotEmpty(dto.getMaterialCode())) {
                qw.eq("materielid", dto.getMaterialCode());
            }
            if (StrUtil.isNotEmpty(dto.getMaterialName())) {
                qw.like("material_name", dto.getMaterialName());
            }
        }
        List<WmsQtMaterial> wmsQtMaterials = wmsQtMaterialMapper.selectList(qw);
        return wmsQtMaterials;
    }

    @Override
    public Boolean getOrderStatus(ProdPlanErpDTO dto) {
        if (ObjectUtil.isEmpty(dto)) {
            throw new CustomException("查询工单状态数据为空");
        }
        Boolean status = true;
        ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("scdd_erp_id", dto.getOrderId()));
        //如果此计划下面的工单有齐套或者工单下发  那么就不允许关闭
        List<ProdOrder> list = prodOrderMapper.selectList(new QueryWrapper<ProdOrder>().eq("plan_code", prodPlan.getPlanCode()));
        if (IterUtil.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                String orderState = list.get(i).getOrderState();
                if ("2".equals(orderState)) {//已齐套
                    return false;
                }
                if ("3".equals(orderState)) {//已下发
                    return false;
                }

            }
        }
        return status;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void planCom(Integer rule) {
        System.out.println("================总成条码生产数量比对开始===============");
        String date05Str = DateUtil.formatDate(new Date()) + " 17:00:00";
        String date20Str = DateUtil.formatDate(new Date()) + " 08:00:00";
        Date date20 = DateUtil.parse(date20Str, "yyyy-MM-dd HH:mm:ss");
        DateTime tomorrow20 = DateUtil.offsetDay(date20, 1);
        String tomorrow20Str = DateUtil.format(tomorrow20, "yyyy-MM-dd HH:mm:ss");
        if (rule.intValue() == TaskEnum.TASK_5.getCode()) {
            //根据任务令查询早上八点至今天下午五点总成生产数量是否合格
            List<ProdCountByTaskTonDTO> listProd = prodOrderMapper.selectByTaskTon(date20Str, date05Str, "t.if_sn_task=0");
            if (IterUtil.isNotEmpty(listProd)) {
                //查询客户条码回传数量是否相等
                listProd.stream().forEach(i -> {
                    Integer sumTaskNo = customerSnMapper.selectByTaskTon(i.getTaskTon(), i.getProductCode());
                    if (sumTaskNo == null) {
                        sumTaskNo = 0;
                    }
                    if (sumTaskNo != i.getSumOr()) {
                        //发邮件告知生产总成数量与实际不一致
                        MailInfoDTO mailInfoDTO = new MailInfoDTO();
                        mailInfoDTO.setSubject("客户条码回传");
                        List<String> recipients = new ArrayList<>();
                        recipients.add("11832@cqld.com");
                        recipients.add("hxu@h-visions-cq.com");
                        mailInfoDTO.setRecipients(recipients);
                        mailInfoDTO.setText("【ems_customer_sn】产品编码【"
                                + i.getProductCode()
                                + "】任务令【"
                                + i.getTaskTon()
                                + "】客户条码回传应传数量【"
                                + i.getSumOr()
                                + "】与实际数量【"
                                + sumTaskNo
                                + "】不一致请尽快核对！");
                        mailApplication.sendSimpleMail(mailInfoDTO);
                    } else if (sumTaskNo == i.getSumOr()) {
                        //如果数量一致判断每条数据回传华为是否正常
                        List<EmsCustomerSn> emsCustomerSns = customerSnMapper.selectList(new QueryWrapper<EmsCustomerSn>()
                                .eq("task_no", i.getTaskTon())
                                .eq("part_no", i.getProductCode())
                        );
                        if (IterUtil.isNotEmpty(emsCustomerSns)) {
                            emsCustomerSns.stream().forEach(em -> {
                                String res = em.getRes();
                                if (StrUtil.isEmpty(res)) {
                                    //发送邮件告知
                                    MailInfoDTO mailInfoDTO = new MailInfoDTO();
                                    mailInfoDTO.setSubject("客户条码回传");
                                    List<String> recipients = new ArrayList<>();
                                    recipients.add("11832@cqld.com");
                                    recipients.add("hxu@h-visions-cq.com");
                                    mailInfoDTO.setRecipients(recipients);
                                    mailInfoDTO.setText("【ems_customer_sn】产品编码【"
                                            + i.getProductCode()
                                            + "】任务令【"
                                            + i.getTaskTon()
                                            + "】关系id【"
                                            + em.getCustomLinkId()
                                            + "】无回传信息请尽快核对！");
                                    mailApplication.sendSimpleMail(mailInfoDTO);
                                } else if (StrUtil.isNotEmpty(res)) {
                                    Map map = JSONUtil.toBean(res, Map.class);
                                    String status = (String) map.get("status");
                                    String message = (String) map.get("message");
                                    if ("500".equals(status)) {
                                        //发送邮件告知
                                        MailInfoDTO mailInfoDTO = new MailInfoDTO();
                                        mailInfoDTO.setSubject("客户条码回传");
                                        List<String> recipients = new ArrayList<>();
                                        recipients.add("11832@cqld.com");
                                        recipients.add("hxu@h-visions-cq.com");
                                        mailInfoDTO.setRecipients(recipients);
                                        mailInfoDTO.setText("【ems_customer_sn】产品编码【"
                                                + i.getProductCode()
                                                + "】任务令【"
                                                + i.getTaskTon()
                                                + "】关系id【"
                                                + em.getCustomLinkId()
                                                + "】回传信息出错【"
                                                + message
                                                + "】请尽快核对！");
                                        mailApplication.sendSimpleMail(mailInfoDTO);
                                    } else {
                                        //更改定时匹配任务状态
                                        ProdPlan prodPlan = new ProdPlan();
                                        prodPlan.setIfSnTask(1);
                                        prodPlanMapper.update(prodPlan, new QueryWrapper<ProdPlan>()
                                                .eq("task_ton", i.getTaskTon())
                                                .eq("product_code", i.getProductCode())
                                        );
                                    }

                                }
                            });
                        }

                    }
                });
            }
        } else if (rule.intValue() == TaskEnum.TASK_20.getCode()) {
            //晚上17点 至第二天早上8点
            List<ProdCountByTaskTonDTO> listProd = prodOrderMapper.selectByTaskTon(date05Str, tomorrow20Str, "t.if_attrIbute_task=0");
            if (IterUtil.isNotEmpty(listProd)) {
                //查询产品条码属性数量是否相等
                listProd.stream().forEach(i -> {
                    //根据任务令查询当天五点至当天八点产品条码属性数量
                    Integer sumTaskNo = barcodeAttributeMapper.selectByTaskTon(i.getTaskTon(), i.getProductCode());
                    if (sumTaskNo == null) {
                        sumTaskNo = 0;
                    }
                    if (sumTaskNo != i.getSumOr()) {
                        //发邮件告知数量与实际不一致
                        MailInfoDTO mailInfoDTO = new MailInfoDTO();
                        mailInfoDTO.setSubject("产品条码回传");
                        List<String> recipients = new ArrayList<>();
                        recipients.add("11832@cqld.com");
                        recipients.add("hxu@h-visions-cq.com");
                        mailInfoDTO.setRecipients(recipients);
                        mailInfoDTO.setText("【EMS_BARCODE_ATTRIBUTE】产品编码【"
                                + i.getProductCode()
                                + "】任务令【"
                                + i.getTaskTon()
                                + "】条码属性回传应传数量【"
                                + i.getSumOr()
                                + "】与实际数量【"
                                + sumTaskNo
                                + "】不一致请尽快核对！");
                        mailApplication.sendSimpleMail(mailInfoDTO);
                    } else {
                        //更改定时匹配任务状态
                        ProdPlan prodPlan = new ProdPlan();
                        prodPlan.setIfAttributeTask(1);
                        prodPlanMapper.update(prodPlan, new QueryWrapper<ProdPlan>()
                                .eq("task_ton", i.getTaskTon())
                                .eq("product_code", i.getProductCode())
                        );
                    }
                });
            }
        }
        System.out.println("================总成条码生产数量比对结束===============");
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void planBomCom(Integer rule) {
        System.out.println("================批次生产数量比对开始===============");
        String date05Str = DateUtil.formatDate(new Date()) + " 17:00:00";
        String date20Str = DateUtil.formatDate(new Date()) + " 08:00:00";
        Date date20 = DateUtil.parse(date20Str, "yyyy-MM-dd HH:mm:ss");
        DateTime tomorrow20 = DateUtil.offsetDay(date20, 1);
        String tomorrow20Str = DateUtil.format(tomorrow20, "yyyy-MM-dd HH:mm:ss");
        if (rule.intValue() == TaskEnum.TASK_5.getCode()) {
            //根据任务令查询昨天八点至今天五点bom生产数量是否合格
            List<ProdCountByTaskTonDTO> listBom = prodOrderMapper.selectByChildCode(date20Str, date05Str);
            this.quaCom(listBom);
        } else if (rule.intValue() == TaskEnum.TASK_20.getCode()) {
            List<ProdCountByTaskTonDTO> listBom = prodOrderMapper.selectByChildCode(date05Str, tomorrow20Str);
            this.quaCom(listBom);
        }
        System.out.println("================批次生产数量比对结束===============");
    }

    @Override
    public AjaxResult getPoversion(String taskTon) {
        AjaxResult entityRevision = tbService.getEntityRevision(taskTon);
        List<Software> listSo = new ArrayList<>();
        List<EntityRevisionDTO> list = (List<EntityRevisionDTO>) entityRevision.get("data");
        if (IterUtil.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                Software software = new Software();
                software.setId(Long.valueOf(i));
                software.setEntityName(list.get(i).getEntityName());
                software.setWorkNumber(list.get(i).getWorkNumber());
                software.setItemNumber(list.get(i).getItemNumber());
                software.setItemVer(list.get(i).getItemVer());
                software.setSoftItem(list.get(i).getSoftItem());
                software.setSoftName(list.get(i).getSoftName());
                software.setUpdatedRevision(list.get(i).getRevision());
                software.setLocation(list.get(i).getSoftLocation());
                software.setModeProcduction(list.get(i).getModeProcduction());
                software.setSpecialRevision(list.get(i).getSpecialRevision());
                software.setCreatedby(list.get(i).getCreateBy());
                software.setCreateddate(list.get(i).getCreateDate());
                software.setUpdatedby(list.get(i).getUpdateBy());
                software.setSegment1(list.get(i).getSegment1());
                software.setZorgid(list.get(i).getZorgid());
                listSo.add(software);
            }

        }
        return AjaxResult.success(listSo);
    }

    @Override
    public AjaxResult uploadPoversion(List<Software> list) {
        if (IterUtil.isNotEmpty(list)) {
            list.stream().forEach(i -> {
//                String xml ="<![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
//                        "<UpdateSoftware>\n" +
//                        "<Import>\n" +
//                        "<EntityName>"+i.getEntityName()+"</EntityName>\n" +
//                        "<WorkNumber>"+i.getWorkNumber()+"</WorkNumber>\n" +
//                        "<ItemNumber>"+i.getItemNumber()+"</ItemNumber>\n" +
//                        "<ItemVer>"+i.getItemVer()+"</ItemVer>\n" +
//                        "<SoftItem>"+i.getSoftItem()+"</SoftItem>\n" +
//                        "<SoftName>"+i.getSoftName()+"</SoftName>\n" +
//                        "<UpdatedRevision>"+i.getUpdatedRevision()+"</UpdatedRevision>\n" +
//                        "<Location>"+i.getLocation()+"</Location>\n" +
//                        "<ModeProcduction>"+i.getModeProcduction()+"</ModeProcduction>\n" +
//                        "<SpecialRevision>"+i.getSpecialRevision()+"</SpecialRevision>\n" +
//                        "<Level>"+i.getLevel()+"</Level>\n" +
//                        "<VendorId>"+i.getVendorId()+"</VendorId>\n" +
//                        "<Created_by>"+i.getCreatedby()+"</Created_by>\n" +
//                        "<Created_date>"+i.getCreateddate()+"</Created_date>\n" +
//                        "<Updated_by>"+i.getUpdatedby()+"</Updated_by>\n" +
//                        "<Updated_date></Updated_date>\n" +
//                        "<Segment1>"+i.getSegment1()+"</Segment1>\n" +
//                        "<Segment2></Segment2>\n" +
//                        "<Segment3></Segment3>\n" +
//                        "<Segment4></Segment4>\n" +
//                        "<Segment5></Segment5>\n" +
//                        "<Zorgid>"+i.getZorgid()+"</Zorgid>\n" +
//                        "</Import>\n" +
//                        "</UpdateSoftware>]]>";

                String date = DateUtil.format(new Date(), "yyyyMMdd'T'HHmmss'Z'");
                String xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?> <soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">   <soap:Body>     <Get_Info_Frmbarcode xmlns=\"http://Auto.huawei.com.cn/\">       <sTaskType>UpdateSoftwareNew</sTaskType>       <sImport><![CDATA[<?xml version=\"1.0\" encoding=\"UTF-8\"?> <UpdateSoftwareNew>\n" +
                        "<Import>\n" +
                        "<EntityName >" + i.getEntityName() + "</ EntityName>\n" +
                        "<WorkNumber >" + i.getWorkNumber() + "</ WorkNumber>\n" +
                        "<ItemNumber>" + i.getItemNumber() + "</ItemNumber>\n" +
                        "<ItemVer>" + i.getItemVer() + "</ItemVer>\n" +
                        "<SoftItem>" + i.getSoftItem() + "</SoftItem>\n" +
                        "<SoftName>" + i.getSoftName() + "</SoftName>\n" +
                        "<UpdatedRevision>" + i.getUpdatedRevision() + "</ UpdatedRevision >\n" +
                        "<Location>" + i.getLocation() + "</Location>\n" +
                        "<ModeProcduction>" + i.getModeProcduction() + "</ ModeProcduction >\n" +
                        "<SpecialRevision>" + i.getSpecialRevision() + "</ SpecialRevision >\n" +
                        "<Level >" + i.getLevel() + "</ Level >\n" +
                        "<VendorId>" + i.getVendorId() + "</VendorId>\n" +
                        "<Created_by>" + i.getCreatedby() + "</Created_by>\n" +
                        "<Created_date>" + i.getCreateddate() + "</Created_date>\n" +
                        "<Updated_by>" + i.getUpdatedby() + "</Updated_by>\n" +
                        "<Updated_date></ Updated_date>\n" +
                        "<Segment1>" + i.getSegment1() + "</Segment1>\n" +
                        "<Segment2></Segment2>\n" +
                        "<Segment3></Segment3>\n" +
                        "<Segment4></Segment4>\n" +
                        "<Segment5></Segment5>\n" +
                        "<Zorgid>" + i.getZorgid() + "</Zorgid>\n" +
                        " </Import>";

                try {

                    //改为https方式回传华为20250416
                    String send = HuaweiInterfaceHttps.sendHuawei(HuaweiInterfaceHttps.serviceUriSoap, HuaweiInterfaceHttps.http_medhod_soap, xml, date);

//                    SoapClient client = SoapClient.create("http://cmes.huawei.com/hw_manufacture/Midlayer.asmx")
//                            .setMethod("Get_Info_Frmbarcode", "http://Auto.huawei.com.cn/")
//                            .setParam("sTaskType", "UpdateSoftware")
//                            .setParam("sImport", xml);
//
//                    // 发送请求，参数true表示返回一个格式化后的XML内容
//                    // 返回内容为XML字符串，可以配合XmlUtil解析这个响应
//                    String send = client.send(true);
                    JSONObject object = XML.toJSONObject(send);
                    Map map3 = JSONUtil.toBean(JSONUtil.toJsonStr(object), Map.class);
                    i.setRes(JSONUtil.toJsonStr(map3));
                    softwareMapper.insert(i);
                } catch (Exception e) {
                    //异常日志记录
                    InterfaceLog interfaceLog = new InterfaceLog();
                    interfaceLog.setSerialNumber(String.valueOf(new Date().getTime()));
                    interfaceLog.setStartTime(new Date());
                    interfaceLog.setInterfaceDirection("WMS->MOM");
                    interfaceLog.setPacketSize("");
                    interfaceLog.setInterfaceRequest(JSONUtil.toJsonStr(list));
                    interfaceLog.setEndTime(new Date());
                    interfaceLog.setInterfaceResponse(e.getMessage());
                    long be = DateUtil.between(interfaceLog.getStartTime(), interfaceLog.getEndTime(), DateUnit.MS);
                    interfaceLog.setTimeConsuming(String.valueOf(be));
                    interfaceLog.setCreateTime(new Date());
                    interfaceLog.setInterfaceType("http");
                    interfaceLog.setInterfaceName("华为外协版本更新");
                    interfaceLogMapper.insert(interfaceLog);
                }

            });
        }
        return AjaxResult.success("上传完毕");
    }

    @Override
    public AjaxResult getInfo(Long planId) {
        ProdPlan pro = getById(planId);

        //HW01正常件需要有BOM子件才能拆分，HW02返修件不需要有BOM子件就可以拆分
//        if("HW01".equals(pro.getType())){
        List<BomInfoErp> list = bomInfoErpMapper.selectList(new QueryWrapper<BomInfoErp>()
                .eq("task_ton", pro.getTaskTon())
        );
        if (IterUtil.isEmpty(list)) {
//                throw new CustomException("HW01正常件需要有BOM子件才能拆分");
            throw new CustomException("HW01/HW02正常件需要有BOM子件才能拆分");
        }
//        }

        //根据产品编码查询工艺路线名称
        List<MesOperations> operations = mesOperationsMapper.selectList(new QueryWrapper<MesOperations>()
                .eq("product_code", pro.getProductCode()));
        if (IterUtil.isNotEmpty(operations)) {
            pro.setRoutingCode(operations.get(0).getRoutingCode());
            pro.setRoutingName(operations.get(0).getRoutingName());
        }
        return AjaxResult.success(pro);
    }

    @Override
    public AjaxResult getGy(Long planId) {
        ProdPlan prodPlan = this.getById(planId);
        //根据新产品编码获取旧产品编码
        MaterialDataErp materialDataErp = materialDataErpMapper.selectOne(new QueryWrapper<MaterialDataErp>()
                .eq("inv_code", prodPlan.getProductCode())
        );
        if (ObjectUtil.isEmpty(materialDataErp)) {
            throw new CustomException("物料主数据中不存在此产品！");
        }

        List<MesOperations> operations = mesOperationsMapper.selectList(new QueryWrapper<MesOperations>()
                .eq("product_code", materialDataErp.getInvCodeOld())
        );
        return AjaxResult.success(operations);
    }

    /**
     * 进行批次数量比对
     *
     * @param listBom
     */
    private void quaCom(List<ProdCountByTaskTonDTO> listBom) {
        if (IterUtil.isNotEmpty(listBom)) {
            listBom.stream().forEach(i -> {
                Integer countMa = barcodeMaterialMapper.selectByCount(i.getProductCode(), i.getTaskTon(), i.getChildCode());
                Integer countRe = barcodeRelationMapper.selectByCount(i.getProductCode(), i.getTaskTon(), i.getChildCode());
                int sumMaRe = countMa + countRe;
                if (i.getSumBom() > sumMaRe) {
                    //发邮件告知数量与实际不一致
                    MailInfoDTO mailInfoDTO = new MailInfoDTO();
                    mailInfoDTO.setSubject("批次物料回传");
                    List<String> recipients = new ArrayList<>();
                    recipients.add("11832@cqld.com");
                    recipients.add("hxu@h-visions-cq.com");
                    mailInfoDTO.setText("【EMS_BARCODE_MATERIAL，EMS_BARCODE_RELATION】产品编码【"
                            + i.getProductCode()
                            + "】任务令【"
                            + i.getTaskTon()
                            + "】子件编码【"
                            + i.getChildCode()
                            + "】批次回传应传数量【"
                            + i.getSumBom()
                            + "】与实际数量【"
                            + sumMaRe
                            + "】不一致请尽快核对！");
                    mailApplication.sendSimpleMail(mailInfoDTO);
                } else if (countMa + countRe >= i.getSumBom()) {
                    //判定物料产品关系追述回传是否正确
                    List<EmsBarcodeRelation> emsBarcodeRelations = barcodeRelationMapper.selectList(new QueryWrapper<EmsBarcodeRelation>()
                            .eq("po", i.getTaskTon())
                            .eq("item_code", i.getProductCode())
                            .eq("son_item_code", i.getChildCode())
                    );
                    if (IterUtil.isNotEmpty(emsBarcodeRelations)) {
                        emsBarcodeRelations.stream().forEach(em -> {
                            String res = em.getRes();
                            if (StrUtil.isEmpty(res)) {
                                //发邮件告知
                                MailInfoDTO mailInfoDTO = new MailInfoDTO();
                                mailInfoDTO.setSubject("批次物料回传");
                                List<String> recipients = new ArrayList<>();
                                recipients.add("11832@cqld.com");
                                recipients.add("hxu@h-visions-cq.com");
                                mailInfoDTO.setText("【EMS_BARCODE_MATERIAL，EMS_BARCODE_RELATION】产品编码【"
                                        + i.getProductCode()
                                        + "】任务令【"
                                        + i.getTaskTon()
                                        + "】子件编码【"
                                        + i.getChildCode()
                                        + "】批次回传无回传信息请尽快核对！");
                                mailApplication.sendSimpleMail(mailInfoDTO);
                            } else if (StrUtil.isNotEmpty(res)) {
                                if (!res.contains("<ErrorCode>0")) {
                                    //发邮件告知
                                    MailInfoDTO mailInfoDTO = new MailInfoDTO();
                                    mailInfoDTO.setSubject("批次物料回传");
                                    List<String> recipients = new ArrayList<>();
                                    recipients.add("11832@cqld.com");
                                    recipients.add("hxu@h-visions-cq.com");
                                    mailInfoDTO.setText("产品编码【"
                                            + i.getProductCode()
                                            + "】任务令【"
                                            + i.getTaskTon()
                                            + "】子件编码【"
                                            + i.getChildCode()
                                            + "】批次回传信息异常【"
                                            + res
                                            + "】请尽快核对！");
                                    mailApplication.sendSimpleMail(mailInfoDTO);
                                } else {
                                    //更改定时匹配任务状态
                                    ProdPlan prodPlan = new ProdPlan();
                                    prodPlan.setIfAttributeTask(1);
                                    prodPlanMapper.update(prodPlan, new QueryWrapper<ProdPlan>()
                                            .eq("task_ton", i.getTaskTon())
                                            .eq("product_code", i.getProductCode())
                                    );
                                }
                            }
                        });
                    }
                }

            });
        }
    }

    private Boolean requestProdWMS(ProdOrderDTO dto) {

        //下发日志记录
        InterfaceLog interfaceLog = new InterfaceLog();
        interfaceLog.setSerialNumber(String.valueOf(new Date().getTime()));
        interfaceLog.setStartTime(new Date());
        interfaceLog.setInterfaceDirection("MOM->WMS");
        interfaceLog.setPacketSize("");
        interfaceLog.setCreateBy(SecurityUtils.getUsername());
        interfaceLog.setCreateTime(new Date());
        interfaceLog.setInterfaceType("http");


        /**
         * 请求参数组装
         */
        InsManuBillsDTO insManuBillsDTO = new InsManuBillsDTO(dto);
        insManuBillsDTO.setCreatemanid(String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
        insManuBillsDTO.setCreateman(String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
        insManuBillsDTO.setCreatemanname(SecurityUtils.getUsername());
        insManuBillsDTO.setSubmitman(SecurityUtils.getUsername());
        List<ManubillDetaildtos> list = this.getMans(dto);
        insManuBillsDTO.setManubill_Detaildtos(list);
        insManuBillsDTO.setCreatedate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        insManuBillsDTO.setAuditman(String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
        insManuBillsDTO.setAuditmanname(SecurityUtils.getUsername());
        insManuBillsDTO.setAuditdate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        String materialCode = dto.getMaterialCode();
        //根据新物料编码获取旧物料编码下发至wms
        MaterialDataErp materialDataErp = materialDataErpMapper.selectOne(new QueryWrapper<MaterialDataErp>()
                .eq("inv_code", materialCode)
        );
        insManuBillsDTO.setMaterielid(materialDataErp.getInvCodeOld());
        insManuBillsDTO.setMaterielnames(dto.getMaterialName());
        insManuBillsDTO.setSeq(10);//暂时默认10
        insManuBillsDTO.setStates("40");//暂时默认审核状态
        insManuBillsDTO.setProductiontype("10");//默认标准生产
        insManuBillsDTO.setBegindate(DateUtil.format(dto.getStartTime(), "yyyy-MM-dd HH:mm:ss"));
        insManuBillsDTO.setEnddate(DateUtil.format(dto.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
        insManuBillsDTO.setWorkshopid("100");//暂时默认车间为100
        insManuBillsDTO.setCardgenerationmode("10");
        insManuBillsDTO.setZapdeltag("N");
        insManuBillsDTO.setBillno(dto.getOrderCode());
        insManuBillsDTO.setPlanqty(dto.getOrderNumber());
        insManuBillsDTO.setFreedom3(dto.getTaskTon());

        ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("plan_code", dto.getPlanCode()));

        insManuBillsDTO.setServiceid(prodPlan.getDeptCode());//erp部门编码
        insManuBillsDTO.setFreedom4(prodPlan.getDeptName());//erp部门名称
        insManuBillsDTO.setFreedom5(prodPlan.getMainOrderId());//erp计划工单id
        insManuBillsDTO.setFreedom6(prodPlan.getPlanCode());//erp计划工单号
        insManuBillsDTO.setFreedom7(prodPlan.getScddErpId());


        List<InsManuBillsDTO> listreq = new ArrayList<>();
        listreq.add(insManuBillsDTO);
        //进行WMS订单接口调用
        String response = HttpUtil.post(IpAddressConstant.WMS_IP + "/api/app/default-manu-bill/ins-manu-bills", JSONUtil.toJsonStr(listreq));
        interfaceLog.setEndTime(new Date());
        long be = DateUtil.between(interfaceLog.getStartTime(), interfaceLog.getEndTime(), DateUnit.MS);
        interfaceLog.setTimeConsuming(String.valueOf(be));
        interfaceLog.setInterfaceRequest(JSONUtil.toJsonStr(listreq));
        interfaceLog.setInterfaceResponse(JSONUtil.toJsonStr(response));
        interfaceLog.setInterfaceName("WMS订单信息");
        interfaceLogMapper.insert(interfaceLog);
        Map map = JSONUtil.toBean(response, Map.class);
        boolean rtnSuccess = (boolean) map.get("rtnSuccess");
        return rtnSuccess;
    }

    private List<ManubillDetaildtos> getMans(ProdOrderDTO dto) {
        List<MaterialDataWmsDTO> maters = this.getMatersPlan(dto);
        List<ManubillDetaildtos> detaildtosList = new ArrayList<>();
        for (int i = 0; i < maters.size(); i++) {
            ManubillDetaildtos manubillDetaildtos = new ManubillDetaildtos();
            manubillDetaildtos.setCreatedate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            manubillDetaildtos.setCreatemanid(String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
            manubillDetaildtos.setCreateman(String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
            manubillDetaildtos.setCreatemanname(SecurityUtils.getUsername());
//            manubillDetaildtos.setFactoryid("Z01YQJ");
            manubillDetaildtos.setFactoryid("2040");//这里后续要改为sap工厂2040
            manubillDetaildtos.setMetricid(maters.get(i).getUnit());
            manubillDetaildtos.setPlanqty(Double.valueOf(maters.get(i).getKitquantity()));
            manubillDetaildtos.setMaterielid(maters.get(i).getMaterielid());
            manubillDetaildtos.setPkid(Long.valueOf(maters.get(i).getChildid() + "001"));//todo 拼接001是临时逻辑处理下发数据重复问题
            manubillDetaildtos.setBillno(dto.getOrderCode());
            manubillDetaildtos.setUseway("10");
            manubillDetaildtos.setServiceid(String.valueOf(SecurityUtils.getLoginUser().getUser().getDeptId()));
            manubillDetaildtos.setStates("40");
            manubillDetaildtos.setUseway("10");
            manubillDetaildtos.setBillno(dto.getOrderCode());
            manubillDetaildtos.setZapdeltag("N");
            manubillDetaildtos.setManubillmainobj(Integer.valueOf(dto.getOrderId()));
            manubillDetaildtos.setSequence(i + 1);
            //根据物料获取工位与线体
            List<StationMaterialLineDTO> list = baseStationMaterialMapper.getlineAndStation(maters.get(i).getMaterielid(), dto.getLineCode());
            if (IterUtil.isNotEmpty(list)) {
                List<String> StationCodes = new ArrayList<>();
                List<String> lines = new ArrayList<>();
                Map<String, List<StationMaterialLineDTO>> map = list.stream().collect(Collectors.groupingBy(e -> e.getStationCode()));
                map.forEach((key, value) -> {
                    StationCodes.add(key);
                    value.stream().forEach(k -> {
                        lines.add(k.getLineCode() + "@@" + k.getLineName());
                    });
                });
                if (lines.size() > 0) {
                    manubillDetaildtos.setFreedom3(lines.get(0));//线体
                }
                manubillDetaildtos.setFreedom4(StationCodes.stream()
                        .collect(Collectors.joining(",")));//工位
            }

            detaildtosList.add(manubillDetaildtos);
        }

        return detaildtosList;
    }

    public String requestOrderWMS(ProdOrderDTO dto) {

        //逻辑改为从生产计划里面获取物料清单进行计算
        List<MaterialDataWmsDTO> maters = this.getMatersPlan(dto);
        QptWmsDTO qptWmsDTO = new QptWmsDTO(dto);
        qptWmsDTO.setFactoryid("2040");//工厂编码暂时写死
        qptWmsDTO.setTransferman(SecurityUtils.getUsername());
        qptWmsDTO.setMaterielListDtos(maters);
        InterfaceLog interfaceLog = new InterfaceLog();
        interfaceLog.setStartTime(new Date());
        //进行WMS齐配套接口调用
        String response = HttpUtil.post(IpAddressConstant.WMS_IP + "/api/app/default-storage-kitting-materiel/calc-storage-kitting-materiel", JSONUtil.toJsonStr(qptWmsDTO));

        //下发日志记录

        interfaceLog.setSerialNumber(String.valueOf(new Date().getTime()));
        interfaceLog.setInterfaceDirection("MOM->WMS");
        interfaceLog.setPacketSize("");
        interfaceLog.setInterfaceRequest(JSONUtil.toJsonStr(qptWmsDTO));
        interfaceLog.setEndTime(new Date());
        interfaceLog.setInterfaceResponse(response);
        long be = DateUtil.between(interfaceLog.getStartTime(), interfaceLog.getEndTime(), DateUnit.MS);
        interfaceLog.setTimeConsuming(String.valueOf(be));
        interfaceLog.setCreateTime(new Date());
        interfaceLog.setInterfaceType("http");
        interfaceLog.setInterfaceName("齐套校验");
        interfaceLogMapper.insert(interfaceLog);

        Map map = JSONUtil.toBean(response, Map.class);
        Boolean rtnSuccess = (Boolean) map.get("rtnSuccess");
        if (!rtnSuccess) {
            return "齐套校验异常:" + (String) map.get("rtnMsg");
        }
        QptWmsDTO qptWmsDTO1 = JSONUtil.toBean((String) map.get("rtnMsg"), QptWmsDTO.class);
        List<MaterialDataWmsDTO> materielListDtos = qptWmsDTO1.getMaterielListDtos();
        String res = "";
        if (IterUtil.isNotEmpty(materielListDtos)) {
            for (int i = 0; i < materielListDtos.size(); i++) {
                if (materielListDtos.get(i).getKitquantity() > materielListDtos.get(i).getQuantity()) {
                    res += "齐套校验失败！物料" + materielListDtos.get(i).getMaterielid() + "仓库剩余数量" + materielListDtos.get(i).getQuantity() + "小于所需数量" + materielListDtos.get(i).getKitquantity() + "\r\n";
                } else {
                    //todo 将齐套校验成功数据进行工单绑定保存
                    WmsQtMaterial wmsQtMaterial1 = wmsQtMaterialMapper.selectOne(new QueryWrapper<WmsQtMaterial>()
                            .eq("order_id", Long.valueOf(dto.getOrderId()))
                            .eq("materielid", materielListDtos.get(i).getMaterielid()));

                    WmsQtMaterial wmsQtMaterial = new WmsQtMaterial();
                    BeanUtil.copyProperties(i, wmsQtMaterial);
                    wmsQtMaterial.setPlanCode(dto.getPlanCode());
                    wmsQtMaterial.setOrderId(Long.valueOf(dto.getOrderId()));
                    wmsQtMaterial.setOrderCode(dto.getOrderCode());
                    wmsQtMaterial.setUnit(materielListDtos.get(i).getUnit());
                    wmsQtMaterial.setMaterialName(materielListDtos.get(i).getMaterialName());
                    wmsQtMaterial.setMaterielid(materielListDtos.get(i).getMaterielid());

                    if (ObjectUtil.isNull(wmsQtMaterial1)) {
                        wmsQtMaterial.setCreateTime(new Date());
                        wmsQtMaterialMapper.insert(wmsQtMaterial);
                    } else {
                        wmsQtMaterial.setUpdateTime(new Date());
                        wmsQtMaterialMapper.update(wmsQtMaterial, new QueryWrapper<WmsQtMaterial>()
                                .eq("order_id", Long.valueOf(dto.getOrderId()))
                                .eq("materielid", materielListDtos.get(i).getMaterielid()));
                    }

                }
            }
        } else {
            return "wms物料无库存";
        }
        if (StrUtil.isNotEmpty(res)) {
            return res;
        } else if (StrUtil.isEmpty(qptWmsDTO1.getWmsbillno())) {
            return "齐套校验失败！wms无返回调拨单号！";
        } else {
            return "齐套校验成功";
        }

    }

    private List<MaterialDataWmsDTO> getMatersPlan(ProdOrderDTO dto) {
        //获取生产计划里面的物料清单
        ProdOrder prodOrder = prodOrderMapper.selectById(dto.getOrderId());
        ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("plan_code", prodOrder.getPlanCode()));
        List<BomInfoErp> list = bomInfoErpMapper.selectList(new QueryWrapper<BomInfoErp>().eq("scdd_erp_id", prodPlan.getScddErpId()));
        List<MaterialDataWmsDTO> listMa = new ArrayList<>();
        list.stream().forEach(i -> {
            MaterialDataWmsDTO materialDataWmsDTO = new MaterialDataWmsDTO();
            materialDataWmsDTO.setMaterialName(i.getChildName());
            materialDataWmsDTO.setMaterielid(i.getChildCode());
            materialDataWmsDTO.setKitquantity(dto.getOrderNumber() * i.getBasicDosage());
            materialDataWmsDTO.setChildid(i.getChildId());
            listMa.add(materialDataWmsDTO);
        });
        return listMa;
    }

    /**
     * 进行WMS物料数据组装
     *
     * @param list
     * @param ids
     * @param orderNumber
     * @return
     */
    public List<MaterialDataWmsDTO> getMaters(List<MaterialDataWmsDTO> list, List<Long> ids, Integer orderNumber) {
        //根据顶层id查询所有子级列表
        List<Long> result = new ArrayList<>();
        List<Long> longs = this.selectChild(result, ids);
        longs.stream().forEach(i -> {
            BaseBomInfo baseBomInfo = baseBomInfoMapper.selectById(i);
            MaterialDataWmsDTO materialDataWmsDTO = new MaterialDataWmsDTO();
            materialDataWmsDTO.setMaterialName(baseBomInfo.getMaterialName());
            materialDataWmsDTO.setMaterielid(baseBomInfo.getMaterialCode());
            materialDataWmsDTO.setKitquantity((Double.valueOf(orderNumber * baseBomInfo.getSetNumber())));
            list.add(materialDataWmsDTO);
        });
        return list;
    }


    public List<Long> selectChild(List<Long> result, List<Long> ids) {
        //用来存取调用自身递归时的参数
        List<Long> temp = new ArrayList();
        //查询数据库中对应id的实体类
        List<BaseBomInfo> sysEnterpriseOrgList = new ArrayList();
        //遍历传递过来的参数ids
        for (Long id : ids) {
            //查询子级架构
            //此处使用mybaatisPlus的条件构造器，查询pid等于id的对象
            //查询结果返回一个list
            sysEnterpriseOrgList = baseBomInfoMapper.selectList(new QueryWrapper<BaseBomInfo>().eq("parent_id", id));
            //遍历list获取符合条件的对象的id值，一份存到temp中用作递归的参数，并存到全局变量中用来获取所有符合条件的id
            for (BaseBomInfo s : sysEnterpriseOrgList) {
                temp.add(s.getId());
                result.add(s.getId());
            }
        }
        if (temp.size() != 0 && temp != null) {
            selectChild(result, temp);
        }
        return result;
    }


    public void sendOrderMES(ProdOrderDTO dto) {
        //下发日志记录
        InterfaceLog interfaceLog = new InterfaceLog();
        interfaceLog.setSerialNumber(String.valueOf(new Date().getTime()));
        interfaceLog.setStartTime(new Date());
        interfaceLog.setInterfaceDirection("MOM->MES");
        interfaceLog.setPacketSize("");

        //封装发送队列数据
        OrderInfoUpDTO orderInfoUpDTO = new OrderInfoUpDTO();
        orderInfoUpDTO.setInterface("ORDER_INFO");

        OrderInfoDTO orderInfoDTO = new OrderInfoDTO();

        ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("plan_code", dto.getPlanCode()));

        orderInfoDTO.setFPlanNo(dto.getOrderCode());
        orderInfoDTO.setFProdLineNo(dto.getLineCode());
        orderInfoDTO.setFProdLineName(dto.getLineName());
        orderInfoDTO.setProcessRoute(dto.getRoutingCode());

        MaterialDataErp materialDataErp = materialDataErpMapper.selectOne(new QueryWrapper<MaterialDataErp>()
                .eq("inv_code", dto.getMaterialCode())
        );
        orderInfoDTO.setFNumber(materialDataErp.getInvCodeOld());

        orderInfoDTO.setFNum(String.valueOf(dto.getOrderNumber()));
        orderInfoDTO.setFPlanStartDate(DateUtil.format(dto.getStartTime(), "yyyy-MM-dd HH:mm:ss"));
        orderInfoDTO.setFPlanEndDate(DateUtil.format(dto.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
        orderInfoDTO.setRemark(dto.getRemarks() == null ? "1" : dto.getRemarks());
        orderInfoDTO.setTaskTon(dto.getTaskTon());
        if (("HW01".equals(prodPlan.getType()))) {
            orderInfoDTO.setType("1");
        } else if (("HW02".equals(prodPlan.getType()))) {
            orderInfoDTO.setType("2");
        }
        orderInfoUpDTO.setBody(orderInfoDTO);
        interfaceLog.setInterfaceRequest(JSONUtil.toJsonStr(orderInfoUpDTO));
        interfaceLog.setInterfaceName("MES订单任务");

        // todo 发送MOM_to_MES_LineNo队列 放到最后发送队列不然事务控制不了
//        myMQTTClient.publish(JSONUtil.toJsonStr(orderInfoUpDTO),"MOM_to_MES_Line01",1,true);
        //这里的发送逻辑是根据工单的产线发送到不同的主题 D180<line01>  D250<line02>
        if ("Line01".equals(dto.getLineCode())) {
//            myProducer.sendTopic(JSONUtil.toJsonStr(orderInfoUpDTO));
            //todo 改为接口方式传输
            shipmentService.sendOrderInfoLine01(orderInfoUpDTO);
        } else if ("Line02".equals(dto.getLineCode())) {
//            myProducer.sendTopic02(JSONUtil.toJsonStr(orderInfoUpDTO));
            //todo 改为接口方式传输
            shipmentService.sendOrderInfoLine02(orderInfoUpDTO);
        }
        interfaceLog.setEndTime(new Date());
        interfaceLog.setInterfaceResponse(dto.getLineCode() + "队列发送成功");
        long be = DateUtil.between(interfaceLog.getStartTime(), interfaceLog.getEndTime(), DateUnit.MS);
        interfaceLog.setTimeConsuming(String.valueOf(be));
        interfaceLog.setCreateBy(SecurityUtils.getUsername());
        interfaceLog.setCreateTime(new Date());
        interfaceLog.setInterfaceType("activeMQ");
        interfaceLogMapper.insert(interfaceLog);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createProd(ProdOrderDTO dto) {
        //拆分前先判断计划数量与已下发数量是不是相等
        if (dto.getPlanNumber() == dto.getComNumber()) {
            throw new CustomException("计划数量与已下发数量相等，无法生成工单");
        }
        //根据计划编码找到计划单的状态，判断是否是关闭状态
        ProdPlan pr = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("plan_code", dto.getPlanCode()));
        if (2 == pr.getPlanState()) {
            throw new CustomException("此计划工单已关闭无法进行拆分");
        }
        ProdOrder prodOrder = new ProdOrder();
        BeanUtil.copyProperties(dto, prodOrder);

        //根据产品编码获取产品名称
        SetModel setModel = setModelMapper.selectOne(new QueryWrapper<SetModel>().eq("model_des_local_code", dto.getProductCode()));
        if (ObjectUtil.isNotNull(setModel)) {
            prodOrder.setProductName(setModel.getLedName());
        }
        //根据物料编码获取物料名称
        BaseMaterial baseMaterial = baseMaterialMapper.selectOne(new QueryWrapper<BaseMaterial>().eq("material_code", dto.getMaterialCode()));
        if (ObjectUtil.isNotNull(baseMaterial)) {
            prodOrder.setMaterialName(baseMaterial.getMaterialName());
        }
        //根据产线编码获取产线名称
        BaseShop shop = baseShopMapper.selectOne(new QueryWrapper<BaseShop>().eq("shop_code", dto.getLineCode()));
        if (ObjectUtil.isNotNull(shop)) {
            prodOrder.setLineName(shop.getShopName());
        }
        //根据工艺路线编码获取工艺路线名称
        List<MesOperations> mesOperations = mesOperationsMapper.selectList(new QueryWrapper<MesOperations>().eq("routing_code", dto.getRoutingCode()));
        if (ObjectUtil.isNotNull(mesOperations)) {
            prodOrder.setRoutingName(mesOperations.get(0).getRoutingName());
        }

        prodOrder.setCreateBy(SecurityUtils.getUsername());
        prodOrder.setCreateTime(new Date());
        prodOrder.setOrderCode(iBaseSerialNumberService.getSerialNumber("GD"));
//        prodOrder.setOrderCode(String.valueOf(new Date().getTime()));
        prodOrder.setOrderState(OrderConstants.Implementation);
        prodOrderMapper.insert(prodOrder);
        //生产工单之后修改生产计划的完工数量
        ProdPlan prodPlan = new ProdPlan();
        //工单完工数量由产线给到从生产队列里面取，计划里面的完工数量改为已下发数量
        prodPlan.setComNumber(dto.getComNumber() + dto.getOrderNumber());
        prodPlan.setSurplusNumber(dto.getPlanNumber() - prodPlan.getComNumber());
        //如果剩余可下发量为0，那么就关闭计划工单
        if (prodPlan.getSurplusNumber().intValue() == 0) {
            prodPlan.setPlanState(2);
        }
        prodPlanMapper.update(prodPlan, new QueryWrapper<ProdPlan>().eq("plan_code", dto.getPlanCode()));
        return "拆分成功";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String orderSync(List<ProdPlanErpDTO> list) {

        Date startDate = new Date();

        if (IterUtil.isEmpty(list)) {
            throw new CustomException("生产工单同步数据不能为空");
        }

        list.stream().forEach(i -> {

            //只接收HW01和HW02类型的数据
            if (!("HW01".equals(i.getType()) || "HW02".equals(i.getType()))) {
                throw new CustomException("MOM系统不接收HW01、HW02以外的订单数据");
            }

            //获取创建BOM的生产订单唯一id
            String scddErpId = null;
            List<BomInfoErp> bomInfoErps = bomInfoErpMapper.selectList(new QueryWrapper<BomInfoErp>()
                    .eq("task_ton", i.getTaskTon())
            );
            if (IterUtil.isNotEmpty(bomInfoErps)) {
                scddErpId = bomInfoErps.get(0).getScddErpId();
            }

            //根据工单唯一编码先查询有没有生产计划
            ProdPlan prod = new ProdPlan(i);
            ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>()
                    .eq("plan_code", i.getOrderNumber())
            );
            if(ObjectUtil.isNotEmpty(prodPlan)){
                prodPlanMapper.update(prod,new QueryWrapper<ProdPlan>()
                        .eq("plan_code",i.getOrderNumber())
                );
            }else {
                prod.setScddErpId(scddErpId);
                prodPlanMapper.insert(prod);
            }




            //工序
            List<ProdPlanOrderProcessErpDTO> prodPlanOrderProcess = i.getProdPlanOrderProcess();
            if (IterUtil.isNotEmpty(prodPlanOrderProcess)) {
                prodPlanOrderProcess.stream().forEach(j -> {
                    ProdPlanOrderProcessErp prodPlanOrderProcess1 = new ProdPlanOrderProcessErp();
                    BeanUtil.copyProperties(j, prodPlanOrderProcess1);
                    prodPlanOrderProcess1.setPlanId(prod.getPlanId());
                    proPlanOrderProcessErpMapper.insert(prodPlanOrderProcess1);
                });
            }

//            }

        });
        //日志记录
        interfaceLogUtil.insertLog(JSONUtil.toJsonStr(list),
                startDate, new Date(), InterfaceLogUtil.DIR_MOM_SAP,
                InterfaceLogUtil.TYPE_HTTP,
                "工单数据同步成功",
                InterfaceLogUtil.INTERFACENAME_SAPGDTB
        );
        return "同步成功";
    }

    @Override
    public List<BomInfoErp> getBomInfoErpList(BomInfoErp bomInfoErp) {
        QueryWrapper<BomInfoErp> qw = new QueryWrapper<>();

        if (ObjectUtil.isNotNull(bomInfoErp)) {

            if (StrUtil.isNotEmpty(bomInfoErp.getPlanCode())) {
                ProdPlan prodPlan = prodPlanMapper.selectOne(new QueryWrapper<ProdPlan>().eq("plan_code", bomInfoErp.getPlanCode()));
                if (ObjectUtil.isNotNull(prodPlan)) {
                    qw.eq("scdd_erp_id", prodPlan.getScddErpId());
                } else {
                    if (StrUtil.isNotEmpty(bomInfoErp.getScddErpId())) {
                        qw.eq("scdd_erp_id", bomInfoErp.getScddErpId());
                    }
                }
            }

            if (StrUtil.isNotEmpty(bomInfoErp.getChildCode())) {
                qw.eq("child_code", bomInfoErp.getChildCode());
            }
            if (StrUtil.isNotEmpty(bomInfoErp.getChildName())) {
                qw.like("child_name", bomInfoErp.getChildName());
            }
        }
        return bomInfoErpMapper.selectList(qw);
    }


}
